package org.breathe.dynamic.thread.pool.core.refresh;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.breathe.dynamic.thread.pool.core.event.RefreshEvent;
import org.breathe.dynamic.thread.pool.core.executor.ThreadPoolExecutorRegistry;
import org.breathe.dynamic.thread.pool.core.handler.ConfigHandler;
import org.breathe.thread.pool.common.constant.BreatheDtpConstant;
import org.breathe.thread.pool.common.entity.BreatheDtpProperties;
import org.breathe.thread.pool.common.enums.ConfigFileTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.context.event.ApplicationEventMulticaster;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * 抽象刷新
 * @author: breathe
 * @createTime: 2025-04-13
 */
@Slf4j
public abstract class AbstractRefresher implements Refresher {
    @Autowired
    private BreatheDtpProperties breatheDtpProperties;

    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;

    @Override
    public void refresh(String content, ConfigFileTypeEnum fileTypeEnum) {
        if (StrUtil.isBlank(content) || Objects.isNull(fileTypeEnum)) {
            return ;
        }
        try {
            final Map<Object, Object> properties = ConfigHandler.getInstance().parseConfig(content, fileTypeEnum);
            doRefresh(properties);
        } catch(IOException ex) {
            log.error("breathe dynamicTp refresh error, content: {}, fileType: {}", content, fileTypeEnum, ex);
        }
    }

    private void doRefresh(Map<Object, Object> properties) {
        ConfigurationPropertySource sources = new MapConfigurationPropertySource(properties);
        Binder binder = new Binder(sources);
        BindResult<BreatheDtpProperties> bind = binder.bind(BreatheDtpConstant.MAIN_PROPERTIES_PREFIX, Bindable.ofInstance(breatheDtpProperties));
        BreatheDtpProperties bindProperties = bind.get();
        ThreadPoolExecutorRegistry.refresh(bindProperties);
        publishEvent();
    }

    /**
     * 及时告知其他模块，我们的配置发生了变化，重新评估状态。
     */
    private void publishEvent() {
        RefreshEvent event = new RefreshEvent(this, breatheDtpProperties);
        applicationEventMulticaster.multicastEvent(event);
    }
}
